/**
 * Generate code from /{{projectName}}-user/src/main/java/{{packageName}}/core/{{modules}}/service/impl/{{entities@SQL}}ServiceImpl.java.hbs
 */
// @SkipOverwrite
package cn.ibizlab.core.ad.service.impl;

import cn.ibizlab.core.ad.domain.SysDepartment;
import cn.ibizlab.core.ad.domain.SysOrganizationalRole;
import cn.ibizlab.util.enums.Entities;
import cn.ibizlab.util.errors.BadRequestAlertException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.*;

/**
 * 实体[部门] 服务对象接口实现
 *
 * @author generator
 */
@Slf4j
@Service("SysDepartmentService")
public class SysDepartmentServiceImpl extends AbstractSysDepartmentService {

    @Override
    public SysDepartment getDraft(SysDepartment et) {
        List<SysOrganizationalRole> group = new ArrayList<>();
        group.add(new SysOrganizationalRole().setName("默认组").setSort(100L));
        et.setGroups(group);
        return super.getDraft(et);
    }

    private Object lock = new Object();

    @Override
    @Cacheable(value = "sysorganization", key = "'deptoptions:'+#p0.organizationId")
    public List<SysDepartment> options(SysDepartment dto) {
        synchronized (lock) {
            if(ObjectUtils.isEmpty(dto.getOrganizationId()))
                throw new BadRequestAlertException("未指定组织机构标识", Entities.SYS_DEPARTMENT.toString(), "");
            List<SysDepartment> all = sysOrganizationService.get(dto.getOrganizationId()).getDepartments();
            if(ObjectUtils.isEmpty(all))
                return Collections.emptyList();

            String rootId = dto.getOrDefault("root", null);
            Map<String, List<SysDepartment>> map = new HashMap<>();
            List<SysDepartment> list = new ArrayList<>();

            for (SysDepartment item : all) {
                list.add(item.copyTo(new SysDepartment(), false));
            }

            for (SysDepartment item : list) {
                String parentId = item.getParentId();
                if (!ObjectUtils.isEmpty(parentId)) {
                    List<SysDepartment> group = map.getOrDefault(parentId, new ArrayList<>());
                    group.add(item);
                    map.put(parentId, group);
                }
            }

            // 遍历所有的Map对象，将其放入对应的parent_id对应的List的children属性中
            for (SysDepartment item : list) {
                List<SysDepartment> children = map.get(item.getId());
                if (!ObjectUtils.isEmpty(children)) {
                    item.setChildren(children);
                }
            }

            // 将没有parent_id的Map对象放入根节点List中，并返回根节点List
            List<SysDepartment> result = new ArrayList<>();
            for (SysDepartment item : list) {
                if ((item.getParentId() == null && rootId == null) || (rootId != null && rootId.equals(item.getParentId()))) {
                    result.add(item);
                    if (item.getParentId() != null)
                        item.setParentIds(Arrays.asList(item.getParentId()));
                    calculateParentAndSubIds(item);
                }
            }
            return result;
        }
    }

    private void calculateParentAndSubIds(SysDepartment node) {
        if(node.getParentIds()==null)
            node.setParentIds(new ArrayList<>());
        if(node.getSubIds()==null)
            node.setSubIds(new ArrayList<>());
        if(!ObjectUtils.isEmpty(node.getChildren())) {
            node.getChildren().forEach(child -> {
                child.setParentIds(new ArrayList<>());
                child.getParentIds().addAll(node.getParentIds());
                child.getParentIds().add(node.getId());
                calculateParentAndSubIds(child);
                node.getSubIds().add(child.getId());
                node.getSubIds().addAll(child.getSubIds());
            });
        }
    }

    private SysDepartment findNodeById(SysDepartment dto) {
        if(ObjectUtils.isEmpty(dto.getId()))
            throw new BadRequestAlertException("未指定部门标识", Entities.SYS_DEPARTMENT.toString(), "");
        if(ObjectUtils.isEmpty(dto.getOrganizationId()))
            getById(dto.getId()).copyTo(dto,false);
        List<SysDepartment> treeList = this.getSelf().options(dto);
        return findNodeById(treeList,dto.getId());
    }

    private SysDepartment findNodeById(List<SysDepartment> treeList, String id) {
        for(SysDepartment item : treeList) {
            if (item.getId().equals(id))
                return item;
            else if (!ObjectUtils.isEmpty(item.getChildren())) {
                SysDepartment ret = findNodeById(item.getChildren(), id);
                if(ret != null)
                    return ret;
            }

        }
        return null;
    }

    @Override
    @Cacheable(value = "sysorganization", key = "'deptparentids:'+#p0.id")
    public List<String> parentIds(SysDepartment dto) {
        List<String> ids = new ArrayList<>();
        try {
            SysDepartment rootNode = findNodeById(dto);
            if (rootNode != null)
                ids = rootNode.getParentIds();
        }catch (Exception ex) {
            return ids;
        }
        return ids;
    }

    @Override
    @Cacheable(value = "sysorganization", key = "'deptsubids:'+#p0.id")
    public List<String> subIds(SysDepartment dto) {
        List<String> ids = new ArrayList<>();
        try {
            SysDepartment rootNode = findNodeById(dto);
            if (rootNode != null)
                ids = rootNode.getSubIds();
        }catch (Exception ex) {
            return ids;
        }
        return ids;
    }

    @Override
    @CacheEvict(value = "sysorganization", allEntries = true)
    public SysDepartment cacheEvict(SysDepartment dto) {
        return super.cacheEvict(dto);
    }

    @Override
    @CacheEvict(value = "sysorganization", allEntries = true)
    public boolean create(SysDepartment et) {
        if(ObjectUtils.isEmpty(et.getGroups())){
            List<SysOrganizationalRole> group = new ArrayList<>();
            group.add(new SysOrganizationalRole().setName("默认组").setSort(100L));
            et.setGroups(group);
        }
        return super.create(et);
    }

    @Override
    @CacheEvict(value = "sysorganization", allEntries = true)
    public boolean update(SysDepartment et) {
        if(!super.update(et))
            return false;
        if(et.getGroups() == null)
            et.setGroups(new ArrayList<>());
        if(ObjectUtils.isEmpty(et.getGroups())){
            SysOrganizationalRole group = new SysOrganizationalRole().setName("默认组").setDepartment(et).setDepartmentId(et.getId()).setSort(100L);
            this.sysOrganizationalRoleService.create(group);
            et.getGroups().add(group);
        }
        return true;
    }

    @Override
    @CacheEvict(value = "sysorganization", allEntries = true)
    public boolean remove(SysDepartment et) {
        return super.remove(et);
    }


}